home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
JCSM Shareware Collection 1993 November
/
JCSM Shareware Collection - 1993-11.iso
/
cl720
/
sst115j.lzh
/
SSTFLD.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-07-18
|
20KB
|
710 lines
/* ------------------------------------------------------------------------ */
/* sstfield.c */
/* high-level formatted input routines */
/* */
/* CopyRight (C) 1991,1992 Steven Lutrov. All rights reserved. */
/* ------------------------------------------------------------------------ */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <alloc.h>
#include <mem.h>
#include <string.h>
#include <conio.h>
#include "sstvid.h"
#include "sstwin.h"
#include "sstkey.h"
#include "ssthlp.h"
#define _isalpha(c) (isalpha(c) || isspace(c))
#define _isalnum(c) (isalnum(c) || isspace(c))
/* ------------------------------------------------------------------------ */
/* local prototypes */
/* ------------------------------------------------------------------------ */
static void addfield (WINDOW *wnd, FIELD *fld);
static void dispfield (WINDOW *wnd, char *bf, char *msk);
static void datavalue (WINDOW *wnd, FIELD *fld, int n);
static void postprocess (FIELD *fld);
static void preprocess (FIELD *fld, int *c, int p);
static void insertstatus (void);
static int readfield (WINDOW *wnd, FIELD *fld);
static void rjust (char *s);
static void rjustzf (char *s);
static int esdefault (int c);
static int spaces (char *c);
static int testftype (FIELD *fld, int c);
static void processhelp (FIELD *fld);
static int esinputline (int c);
static void deferrorfunc (char *s);
int insertmode = FALSE; /* insert mode, TRUE/FALSE */
int (*fend) (int) = esdefault; /* field end keystroke func */
extern int helpkey; /* key to activate help */
/* ------------------------------------------------------------------------ */
/* initialize a template */
/* ------------------------------------------------------------------------ */
void Finittemplate(WINDOW *wnd)
{
FIELD *fld, *fl;
fld = FHEAD;
while (fld) {
fl = fld->fnxt;
free(fld);
fld = fl;
}
FHEAD = NULL;
}
/* ------------------------------------------------------------------------ */
/* establish a field in a template */
/* ------------------------------------------------------------------------ */
FIELD *Festablish(WINDOW *wnd, int cl, int rw, char *msk,
char *bf, int ty, int flags)
{
FIELD *fld;
if ( (fld = malloc(sizeof(FIELD))) == NULL)
return NULL;
fld->fmask = msk;
fld->frow = rw;
fld->fcol = cl;
fld->fbuff = bf;
fld->ftype = ty;
fld->fprot = 0;
fld->fnxt = fld->fprv = NULL;
fld->fvalid = NULL;
fld->ferror = deferrorfunc;
fld->fvalid = NULL;
fld->helptype = HELP_KEYED;
fld->fhwin = NULL;
fld->fprevalid = NULL;
fld->flx = fld->fly = 0;
fld->fflags = flags;
addfield(wnd, fld);
return fld;
}
/* ------------------------------------------------------------------------ */
/* creates a single input line in a window */
/* ------------------------------------------------------------------------ */
char *Finputline(char *p, char *bf, int x, int y, int l, int t)
{
WINDOW *wnd;
char *msk, *buf;
int c;
if ((msk = malloc(l)) == NULL)
return (NULL);
if ((buf = malloc(l)) == NULL)
return (NULL);
memset(msk,'_',l);
memset(buf,32,l);
msk[l-1] = '\x0';
memcpy(buf,bf,l);
if ((wnd = Westablish(x, y, 3, strlen(p)+l+4)) == NULL)
return (NULL);
Wsetcolour(wnd, WIN_BORDER, LIGHTGRAY, WHITE, BRIGHT);
Wsetcolour(wnd, WIN_TITLE, LIGHTGRAY, RED, DIM);
Wsetcolour(wnd, WIN_FACE, LIGHTGRAY, BLACK, DIM);
Wsetcolour(wnd, WIN_ACCENT, GREEN, BLACK, DIM);
Wsetcolour(wnd, WIN_FLDFACE, LIGHTGRAY, RED, DIM);
Wsettitle(wnd, "[Input line]",JUST_L);
Wshow(wnd);
Wprompt(wnd,0,0, p);
Finittemplate(wnd);
Festablish(wnd, strlen(p)+2,0, msk, buf, t,0);
Fendfunc(esinputline);
c = Fdataentry(wnd,1);
Fendfunc(NULL);
buf[l-1] = '\x0';
Wdelete(wnd);
return (c == ENTER ? buf : bf);
}
/* ------------------------------------------------------------------------ */
/* display all the fields in a window */
/* ------------------------------------------------------------------------ */
void Ftally(WINDOW *wnd)
{
FIELD *fld;
fld = FHEAD;
while (fld != NULL) {
datavalue(wnd, fld,WFIELD);
fld = fld->fnxt;
}
}
/* ------------------------------------------------------------------------ */
/* set a field's help window */
/* ------------------------------------------------------------------------ */
void Fsethelpwin(FIELD *fld, char *hwin, int x, int y)
{
fld->fhwin=hwin;
fld->flx = x;
fld->fly = y;
}
/* ------------------------------------------------------------------------ */
/* clear a template to all blanks */
/* ------------------------------------------------------------------------ */
void Fcleartemplate(WINDOW *wnd)
{
FIELD *fld;
char *bf, *msk;
fld = FHEAD;
while (fld != NULL) {
bf = fld->fbuff;
msk = fld->fmask;
while (*msk) {
if (*msk == FIELDCHAR)
*bf++ = ' ';
msk++;
}
fld = fld->fnxt;
}
Ftally(wnd);
}
/* ------------------------------------------------------------------------ */
/* clear a template to all nulls */
/* ------------------------------------------------------------------------ */
void Fnulltemplate(WINDOW *wnd)
{
FIELD *fld;
char *bf, *msk;
fld = FHEAD;
while (fld != NULL) {
bf = fld->fbuff;
msk = fld->fmask;
while (*msk) {
if (*msk == FIELDCHAR)
*bf++ = 0x00;
msk++;
}
fld = fld->fnxt;
}
Ftally(wnd);
}
/* ------------------------------------------------------------------------ */
/* Process data entry for a screen template. */
/* ------------------------------------------------------------------------ */
int Fdataentry(WINDOW *wnd, int p)
{
FIELD *fld;
int exitcode, isvalid, dir = DOWN;
int done=FALSE;
int oldhelpkey = helpkey;
Ftally(wnd);
fld = FHEAD;
/* ---- collect data from keyboard into screen ---- */
while (fld != NULL && done == FALSE) {
Hset(fld->fhwin, fld->flx, fld->fly);
helpkey = (fld->fhelp) ? 0 : oldhelpkey;
Wcursor(wnd, fld->fcol, fld->frow);
if (fld->fprot == FALSE) {
Wrevvideo(wnd);
datavalue(wnd, fld,WACCENT);
Wcursor(wnd, fld->fcol, fld->frow);
exitcode = readfield(wnd, fld); /* process */
isvalid = (exitcode != ESC && fld->fvalid) ?
(*(fld->fvalid))(fld->fbuff) : OK;
}
else { /* protected field */
switch (dir) {
case DOWN : exitcode = RIGHT;
break;
case UP : exitcode = LEFT;
break;
}
isvalid = OK;
}
if (isvalid == OK) {
Wresetvideo(wnd);
datavalue(wnd, fld,WFIELD);
switch (exitcode) { /* passed edit */
case F1 : if (fld->fhelp) {
(*(fld->fhelp))(fld->fbuff);
datavalue(wnd, fld,WFIELD);
}
break;
case DOWN :
case '\r' :
case '\t' :
case RIGHT :
dir = DOWN;
if ( (exitcode == '\r') && (p) )
done = fend(exitcode);
else {
fld = fld->fnxt;
if (fld == NULL)
fld = FHEAD;
processhelp(fld);
}
break;
case UP :
case LEFT : dir = UP;
fld = fld->fprv;
if (fld == NULL)
fld = FTAIL;
processhelp(fld);
break;
case PGUP :
case HOME : dir = UP;
if (p)
done = fend(exitcode);
else {
fld = FHEAD;
processhelp(fld);
}
break;
case PGDN :
case END : dir = DOWN;
if (p)
done = fend(exitcode);
else {
fld = FTAIL;
processhelp(fld);
}
break;
default : done = fend(exitcode);
break;
}
}
}
helpkey = oldhelpkey;
return (exitcode);
}
/* ------------------------------------------------------------------------ */
/* View data entry for a screen template. */
/* ------------------------------------------------------------------------ */
int Fdataview(WINDOW *wnd)
{
int c;
vhidecur();
Ftally(wnd);
c = kgetch();
vshowcur();
return (c);
}
/* ------------------------------------------------------------------------ */
/* display a window prompt */
/* ------------------------------------------------------------------------ */
void Wprompt(WINDOW *wnd, int x, int y, char *s)
{
Wcursor(wnd, x, y);
Wprintf(wnd, s);
}
/* ------------------------------------------------------------------------ */
/* set the help function for a field */
/* ------------------------------------------------------------------------ */
void Fhelpfunc(FIELD *fld, void (*func)(char *), int w)
{
fld->fhelp = func;
fld->helptype = w;
}
/* ------------------------------------------------------------------------ */
/* set the error function for a field */
/* ------------------------------------------------------------------------ */
void Ferrorfunc(FIELD *fld, void (*func)(char *))
{
fld->ferror = func;
}
/* ------------------------------------------------------------------------ */
/* set the help function for a field */
/* ------------------------------------------------------------------------ */
void Fendfunc(int (*func) (int))
{
if (func)
fend = func;
else
fend = esdefault;
}
/* ------------------------------------------------------------------------ */
/* add a field to the end of the list */
/* ------------------------------------------------------------------------ */
static void addfield(WINDOW *wnd, FIELD *fld)
{
if (FTAIL) {
fld->fprv = FTAIL;
FTAIL->fnxt = fld;
}
FTAIL = fld;
if (!FHEAD)
FHEAD = fld;
}
/* ------------------------------------------------------------------------ */
/* display a data field */
/* ------------------------------------------------------------------------ */
static void dispfield(WINDOW *wnd, char *bf, char *msk)
{
while (*msk) {
Wputch(wnd, *msk != FIELDCHAR ? *msk : *bf++);
msk++;
}
}
/* ------------------------------------------------------------------------ */
/* display a data field */
/* ------------------------------------------------------------------------ */
static void datavalue(WINDOW *wnd, FIELD *fld, int n)
{
char *msk = fld->fmask;
char *bf = fld->fbuff;
int x = fld->fcol+1;
while (*msk) {
displ(wnd, x++, fld->frow+1, *msk != FIELDCHAR ? *msk : *bf++, n);
msk++;
}
}
/* ------------------------------------------------------------------------ */
/* set insert/exchange cursor shape */
/* ------------------------------------------------------------------------ */
static void insertstatus(void)
{
vsetcurtype(insertmode ? 0x0106 : 0x0607);
}
/* ------------------------------------------------------------------------ */
/* process field according to flags after the field edit is complete */
/* ------------------------------------------------------------------------ */
static void postprocess(FIELD *fld)
{
if (fld->fflags & FLD_ZFILL)
rjustzf(fld->fbuff);
else
if (fld->fflags & FLD_RJUST)
rjust(fld->fbuff);
}
/* ------------------------------------------------------------------------ */
/* process user input according to flags as they are keyed in */
/* ------------------------------------------------------------------------ */
static void preprocess(FIELD *fld, int *c, int p)
{
char *bf = fld->fbuff;
if (fld->fprevalid != NULL)
fld->fprevalid(c);
if (fld->fflags & FLD_TOUPPER)
*c = toupper(*c);
if (fld->fflags & FLD_TOLOWER)
*c = tolower(*c);
if (fld->fflags & FLD_TOPROPER) {
if (p == fld->fcol) /* first char in field */
*c = toupper(*c);
if (isspace( *(bf+(p-fld->fcol-1))) )
*c = toupper(*c);
}
}
/* ------------------------------------------------------------------------ */
/* read a field from the keyboard */
/* ------------------------------------------------------------------------ */
static int readfield(WINDOW *wnd, FIELD *fld)
{
char *mask = fld->fmask;
char *buff = fld->fbuff;
int done = FALSE, c, column;
column = fld->fcol;
while (*mask != FIELDCHAR) {
column++;
mask++;
}
while (TRUE) {
Wcursor(wnd, column, fld->frow);
c = kgetch();
if (c < 0x80)
preprocess(fld,&c,column);
(fld->ferror)(NULL); /* clear error function text */
switch (c) {
case '\b':
case LEFT:
if (buff == fld->fbuff) {
done = c == LEFT;
break;
} /* left */
--buff;
do {
--mask;
--column;
} while (*mask != FIELDCHAR);
if (c == LEFT)
break;
case DEL:
movmem(buff+1, buff, strlen(buff));
*(buff+strlen(buff)) = ' ';
Wcursor(wnd, column, fld->frow);
dispfield(wnd, buff, mask);
break;
case RIGHT:
do {
column++;
mask++;
} while (*mask && *mask != FIELDCHAR);
buff++;
break;
case INS:
insertmode ^= TRUE;
insertstatus();
break;
case '.':
if (fld->ftype == FLD_CURR) {
if (*mask++ && *buff == ' ') {
*buff++ = '0';
if (*mask++ && *buff == ' ')
*buff++ = '0';
}
rjust(fld->fbuff);
Wcursor(wnd, fld->fcol, fld->frow);
dispfield(wnd, fld->fbuff, fld->fmask);
column = fld->fcol+strlen(fld->fmask)-2;
mask = fld->fmask+strlen(fld->fmask)-2;
buff = fld->fbuff+strlen(fld->fbuff)-2;
break;
}
default:
if (fend(c)) {
done = TRUE;
break;
}
if (! testftype(fld,c) )
break;
if (insertmode) {
movmem(buff, buff+1, strlen(buff)-1);
dispfield(wnd, buff, mask);
Wcursor(wnd, column, fld->frow);
}
*buff++ = c;
Wputch(wnd, c);
do {
column++;
mask++;
} while (*mask && *mask != FIELDCHAR);
if (!*mask)
c = RIGHT;
break;
} /* switch */
if (!*mask)
done = TRUE;
if (done)
break;
}
if (c != ESC ) {
if (fld->ftype == FLD_CURR) {
if (*mask++ && *buff == ' ') {
*buff++ = '0';
if (*mask++ && *buff == ' ')
*buff++ = '0';
}
}
if (c < 0x80)
postprocess(fld);
Wcursor(wnd, fld->fcol, fld->frow);
dispfield(wnd, fld->fbuff, fld->fmask);
} /* c != ESC */
return c;
}
/* ------------------------------------------------------------------------ */
/* test for a correct field type */
/* ------------------------------------------------------------------------ */
static int testftype(FIELD *fld, int c)
{
int s = 1;
int f = fld->ftype;
if (c > 0x80)
return(1);
switch (f) {
case FLD_CURR :
case FLD_DIGIT :
case FLD_DATE :
case FLD_INT : if (! (s = isdigit(c) ))
(fld->ferror)("Numeric char only");
break;
case FLD_ALNUM : if (! (s = _isalnum(c) ))
(fld->ferror)("Alpha numeric char only");
break;
case FLD_ALPHA : if (! (s = _isalpha(c)))
(fld->ferror)(" Alpha char only ");
break;
case FLD_ASCII : if (! (s = isascii(c) ))
(fld->ferror)(" Ascii char only ");
break;
case FLD_PRINT : if (! (s = isprint(c) ))
(fld->ferror)("Printable char only");
break;
case FLD_XDIGIT : if (! (s = isxdigit(c) ))
(fld->ferror)(" Hexadecimal only ");
break;
}
return(s);
}
/* ------------------------------------------------------------------------ */
/* test for an ending keystroke */
/* ------------------------------------------------------------------------ */
static int esdefault(int c)
{
switch (c) {
case '\r':
case '\n':
case '\t':
case ESC:
case F1:
case F2:
case F3:
case F4:
case F5:
case F6:
case F7:
case F8:
case F9:
case F10:
case PGUP:
case PGDN:
case HOME:
case END:
case UP:
case DOWN:
return TRUE;
default:
return FALSE;
}
}
/* ------------------------------------------------------------------------ */
/* right justify, space fill */
/* ------------------------------------------------------------------------ */
static void rjust(char *s)
{
int len;
len = strlen(s);
while (*s == ' ' || *s == '0' && len) {
len--;
*s++ = ' ';
}
if (len)
while (*(s+(len-1)) == ' ') {
movmem(s, s+1, len-1);
*s = ' ';
}
}
/* ------------------------------------------------------------------------ */
/* right justify, zero fill */
/* ------------------------------------------------------------------------ */
static void rjustzf(char *s)
{
int len;
if (spaces(s))
return;
len = strlen(s);
while (*(s + len - 1) == ' ') {
movmem(s, s + 1, len-1);
*s = '0';
}
}
/* ------------------------------------------------------------------------ */
/* test for spaces */
/* ------------------------------------------------------------------------ */
static int spaces(char *c)
{
while (*c == ' ')
c++;
return !*c;
}
/* ------------------------------------------------------------------------ */
/* */
/* ------------------------------------------------------------------------ */
static void processhelp(FIELD *fld)
{
if (fld->fhelp == NULL)
return;
if ( ((fld->helptype & HELP_INITIAL) || (fld->helptype & HELP_ALWAYS))
&& !(fld->helptype & HELP_DONE) ) {
(*(fld->fhelp))(fld->fbuff);
if (fld->helptype & HELP_INITIAL)
fld->helptype |= HELP_DONE; /* set as done ! */
}
}
/* ------------------------------------------------------------------------ */
/* default endstroke used for single input line */
/* ------------------------------------------------------------------------ */
static int esinputline(int c)
{
switch (c) {
case '\r':
case '\n':
case ESC:
return TRUE;
default:
return FALSE;
}
}
static WINDOW *defewnd = NULL;
/* ------------------------------------------------------------------------ */
/* set the default error function for fields */
/* ------------------------------------------------------------------------ */
static void deferrorfunc(char *s)
{
if (s == NULL) {
if (defewnd) {
Wdelete(defewnd);
defewnd = NULL;
}
}
else {
defewnd = Westablish(50, 22, 3, max(10, strlen(s)+2));
Wsetcolour(defewnd, WIN_ALL, RED, WHITE, BRIGHT);
Wsettitle(defewnd, "[Input Error]",JUST_C);
Wshow(defewnd);
Wprintf(defewnd, s);
vbeep(ERROR);
}
}